package com.game.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import com.game.entity.User;
import com.game.enums.HandType;
import com.game.enums.RoomStatus;
import com.game.exception.BusinessException;
import com.game.model.Card;
import com.game.model.Player;
import com.game.model.PlayerHands;
import com.game.model.Room;
import com.game.repository.UserRepository;
import com.game.service.RoomService;
import com.game.vo.PlayerVO;
import com.game.vo.RoomStatusVO;
import com.game.vo.RoomVO;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
@RequiredArgsConstructor
public class RoomServiceImpl implements RoomService {
    
    private final UserRepository userRepository;
    private final SimpMessagingTemplate messagingTemplate;
    
    // 存储房间信息的内存Map
    private final Map<String, Room> rooms = new ConcurrentHashMap<>();
    
    @Override
    public RoomVO createRoom(Long userId) {
        User creator = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        String roomCode = generateRoomCode();
        while (rooms.containsKey(roomCode)) {
            roomCode = generateRoomCode();
        }
        
        Room room = new Room();
        room.setRoomCode(roomCode);
        room.setStatus(RoomStatus.WAITING);
        room.setCreateTime(new Date());
        room.setCurrentRound(0);
        room.setTotalRounds(13);
        
        Player player = createPlayer(creator);
        room.getPlayers().add(player);
        
        rooms.put(roomCode, room);
        return convertToRoomVO(room);
    }
    
    @Override
    public List<RoomVO> getAvailableRooms() {
        return rooms.values().stream()
                .filter(room -> room.getStatus() == RoomStatus.WAITING)
                .map(this::convertToRoomVO)
                .collect(Collectors.toList());
    }
    
    @Override
    public RoomStatusVO getRoomStatus(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        RoomStatusVO status = new RoomStatusVO();
        status.setRoomCode(roomCode);
        status.setStatus(room.getStatus());
        status.setCurrentRound(room.getCurrentRound());
        status.setTotalRounds(room.getTotalRounds());
        status.setTotalPlayers(room.getPlayers().size());
        status.setReadyPlayersCount((int) room.getPlayers().stream()
                .filter(Player::isReady)
                .count());
        
        // 设置玩家信息，当前玩家可以看到自己的牌
        List<PlayerVO> players = room.getPlayers().stream()
                .map(player -> {
                    PlayerVO vo = new PlayerVO();
                    vo.setId(player.getId());
                    vo.setNickname(player.getNickname());
                    vo.setReady(player.isReady());
                    vo.setScore(player.getScore());
                    // 只有当前玩家能看到自己的牌
                    if (player.getId().equals(userId)) {
                        vo.setCards(player.getCards());
                    } else {
                        vo.setCardsCount(player.getCards().size());
                    }
                    return vo;
                })
                .collect(Collectors.toList());
        
        status.setPlayers(players);
        status.setCurrentPlayerId(room.getCurrentPlayerId());
        status.setLastPlayedCards(room.getLastPlayedCards());
        status.setLastPlayerId(room.getLastPlayerId());
        
        // 设置本轮得分
        status.setRoundScores(room.getRoundScores());
        
        return status;
    }
    
    @Override
    public void joinRoom(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() != RoomStatus.WAITING) {
            throw new BusinessException("房间已开始游戏");
        }
        if (room.getPlayers().size() >= 4) {
            throw new BusinessException("房间已满");
        }
        
        // 检查玩家是否已在房间中
        boolean alreadyInRoom = room.getPlayers().stream()
                .anyMatch(p -> p.getId().equals(userId));
        if (alreadyInRoom) {
            return; // 如果已经在房间中，直接返回
        }
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        Player player = createPlayer(user);
        room.getPlayers().add(player);
        
        // 通知房间内所有玩家
        notifyRoomStatusChanged(room);
    }
    
    @Override
    public void leaveRoom(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() == RoomStatus.PLAYING) {
            throw new BusinessException("游戏进行中，无法离开");
        }
        
        boolean removed = room.getPlayers().removeIf(p -> p.getId().equals(userId));
        if (!removed) {
            throw new BusinessException("玩家不在房间中");
        }
        
        // 重置所有玩家的准备状态
        if (room.getPlayers().size() < 2) {
            room.getPlayers().forEach(p -> p.setReady(false));
        }
        
        // 如果房间空了，删除房间
        if (room.getPlayers().isEmpty()) {
            rooms.remove(roomCode);
        } else {
            // 通知房间内其他玩家
            notifyRoomStatusChanged(room);
        }
    }
    
    @Override
    public void ready(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() != RoomStatus.WAITING) {
            throw new BusinessException("房间状态不正确");
        }
        
        Player player = findPlayer(room, userId);
        player.setReady(true);
        
        log.info("玩家 {} 已准备，当前房间状态: {}, 当前回合: {}", player.getNickname(), room.getStatus(), room.getCurrentRound());
        
        // 检查是否所有玩家都准备好了
        boolean allReady = room.getPlayers().stream().allMatch(Player::isReady);
        int readyCount = (int) room.getPlayers().stream().filter(Player::isReady).count();
        log.info("房间 {} 中已准备玩家数: {}/{}, 是否全部准备: {}", 
                roomCode, readyCount, room.getPlayers().size(), allReady);
        
        // 先通知所有玩家状态更新，显示新的准备状态
        notifyRoomStatusChanged(room);
        
        // 如果所有玩家都已准备且人数足够，开始游戏
        if (room.getPlayers().size() >= 2 && allReady) {
            log.info("所有玩家已准备，准备开始游戏，当前回合: {}", room.getCurrentRound());
            
            // 开始游戏
            startGame(room);
            
            // 再次通知所有玩家游戏已开始
            log.info("游戏已开始，再次通知所有玩家");
            notifyRoomStatusChanged(room);
        }
    }
    
    @Override
    public void cancelReady(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() != RoomStatus.WAITING) {
            throw new BusinessException("房间状态不正确");
        }
        
        Player player = findPlayer(room, userId);
        player.setReady(false);
        
        // 通知房间内所有玩家
        notifyRoomStatusChanged(room);
    }
    
    @Override
    public void playCards(String roomCode, Long userId, List<String> cards) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() != RoomStatus.PLAYING) {
            throw new BusinessException("游戏未开始");
        }
        if (!userId.equals(room.getCurrentPlayerId())) {
            throw new BusinessException("还没轮到你");
        }
        
        Player player = findPlayer(room, userId);
        
        // 验证玩家是否拥有这些牌
        if (!player.getCards().containsAll(cards)) {
            throw new BusinessException("出牌不合法");
        }
        
        // 移除已出的牌
        player.getCards().removeAll(cards);
        room.setLastPlayedCards(new ArrayList<>(cards));
        room.setLastPlayerId(userId);
        
        // 检查是否结束
        if (player.getCards().isEmpty()) {
            finishRound(room, player);
        } else {
            // 轮到下一个玩家
            nextPlayer(room);
        }
    }
    
    @Override
    public void pass(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() != RoomStatus.PLAYING) {
            throw new BusinessException("游戏未开始");
        }
        if (!userId.equals(room.getCurrentPlayerId())) {
            throw new BusinessException("还没轮到你");
        }
        
        // 轮到下一个玩家
        nextPlayer(room);
    }
    
    @Override
    public void startGame(String roomCode, Long userId) {
        Room room = getModelRoom(roomCode);
        
        // 验证是否是房主（第一个加入房间的玩家）
        if (!room.getPlayers().get(0).getId().equals(userId)) {
            throw new BusinessException("只有房主才能开始游戏");
        }
        
        if (room.getStatus() != RoomStatus.WAITING) {
            throw new BusinessException("房间状态不正确");
        }
        
        if (room.getPlayers().size() < 2) {
            throw new BusinessException("玩家数量不足");
        }
        
        // 检查是否所有玩家都已准备
        if (!room.getPlayers().stream().allMatch(Player::isReady)) {
            throw new BusinessException("还有玩家未准备");
        }
        
        startGame(room);
    }
    
    @Override
    public void deleteRoom(String roomCode) {
        getModelRoom(roomCode); // 验证房间存在
        Room room = getModelRoom(roomCode);
        if (room.getStatus() == RoomStatus.PLAYING) {
            throw new BusinessException("游戏进行中，无法删除房间");
        }
        rooms.remove(roomCode);
    }
    
    @Override
    public void submitHand(String roomCode, Long userId, List<Card> frontHand, List<Card> middleHand, List<Card> backHand) {
        Room room = getModelRoom(roomCode);
        if (room.getStatus() != RoomStatus.PLAYING) {
            throw new BusinessException("游戏未开始");
        }
        
        Player player = findPlayer(room, userId);
        
        // 检查玩家是否已提交
        if (player.isReady()) {
            throw new BusinessException("本回合已提交牌型");
        }
        
        // 验证牌型是否合法
        if (!validateHands(frontHand, middleHand, backHand)) {
            throw new BusinessException("牌型不合法");
        }
        
        log.info("用户 {} ({}) 提交牌型，前墩: {}, 中墩: {}, 后墩: {}", 
                 userId, player.getNickname(), frontHand, middleHand, backHand);
        
        // 保存玩家提交的牌型
        room.getSubmittedHands().put(userId, new PlayerHands(frontHand, middleHand, backHand));
        player.setReady(true);
        
        // 通知玩家状态更新，显示该玩家已准备
        notifyRoomStatusChanged(room);
        
        // 如果所有玩家都已提交，开始比牌
        boolean allSubmitted = room.allPlayersSubmitted();
        log.info("房间 {} 当前已提交玩家数: {}/{}，是否全部提交: {}", 
                roomCode, room.getSubmittedHands().size(), room.getPlayers().size(), allSubmitted);
        
        if (allSubmitted) {
            log.info("房间 {} 所有玩家已提交牌型，开始计算得分", roomCode);
            
            // 给前端一点时间接收WebSocket通知
            try {
                Thread.sleep(1000); // 等待1秒
                calculateScores(roomCode);
            } catch (InterruptedException e) {
                log.error("延迟计算得分失败", e);
                Thread.currentThread().interrupt();
                // 如果延迟失败，仍然执行计算
                calculateScores(roomCode);
            }
        }
    }
    
    @Override
    public void calculateScores(String roomCode) {
        Room room = getModelRoom(roomCode);
        Map<Long, PlayerHands> submittedHands = room.getSubmittedHands();
        List<Player> players = room.getPlayers();
        
        log.info("计算房间 {} 的得分，当前玩家数: {}, 已提交牌型数: {}", roomCode, players.size(), submittedHands.size());
        
        // 初始化本轮得分
        room.getRoundScores().clear();
        players.forEach(player -> room.getRoundScores().put(player.getId(), 0));
        
        // 两两比较玩家的牌型
        for (int i = 0; i < players.size(); i++) {
            for (int j = i + 1; j < players.size(); j++) {
                Player player1 = players.get(i);
                Player player2 = players.get(j);
                PlayerHands hands1 = submittedHands.get(player1.getId());
                PlayerHands hands2 = submittedHands.get(player2.getId());
                
                log.info("比较玩家 {} 和玩家 {} 的牌型", player1.getNickname(), player2.getNickname());
                
                // 计算玩家之间的得分
                int player1Score = 0;
                int player2Score = 0;
                
                // 比较前墩（1分）
                int frontCompare = compareHands(hands1.getFrontHand(), hands2.getFrontHand());
                if (frontCompare > 0) {
                    player1Score += 1;
                    player2Score -= 1;
                    log.info("玩家 {} 前墩胜出，得1分，玩家 {} 扣1分", player1.getNickname(), player2.getNickname());
                } else if (frontCompare < 0) {
                    player1Score -= 1;
                    player2Score += 1;
                    log.info("玩家 {} 前墩胜出，得1分，玩家 {} 扣1分", player2.getNickname(), player1.getNickname());
                } else {
                    log.info("前墩平局，无人得分");
                }
                
                // 比较中墩（2分）
                int middleCompare = compareHands(hands1.getMiddleHand(), hands2.getMiddleHand());
                if (middleCompare > 0) {
                    player1Score += 2;
                    player2Score -= 2;
                    log.info("玩家 {} 中墩胜出，得2分，玩家 {} 扣2分", player1.getNickname(), player2.getNickname());
                } else if (middleCompare < 0) {
                    player1Score -= 2;
                    player2Score += 2;
                    log.info("玩家 {} 中墩胜出，得2分，玩家 {} 扣2分", player2.getNickname(), player1.getNickname());
                } else {
                    log.info("中墩平局，无人得分");
                }
                
                // 比较后墩（3分）
                int backCompare = compareHands(hands1.getBackHand(), hands2.getBackHand());
                if (backCompare > 0) {
                    player1Score += 3;
                    player2Score -= 3;
                    log.info("玩家 {} 后墩胜出，得3分，玩家 {} 扣3分", player1.getNickname(), player2.getNickname());
                } else if (backCompare < 0) {
                    player1Score -= 3;
                    player2Score += 3;
                    log.info("玩家 {} 后墩胜出，得3分，玩家 {} 扣3分", player2.getNickname(), player1.getNickname());
                } else {
                    log.info("后墩平局，无人得分");
                }
                
                // 检查是否打枪（三墩都赢）
                if (frontCompare > 0 && middleCompare > 0 && backCompare > 0) {
                    // 打枪奖励分数增加为6分(输家额外扣6分)
                    player1Score += 6;
                    player2Score -= 6;
                    log.info("玩家 {} 打枪成功！额外得6分，玩家 {} 额外扣6分", player1.getNickname(), player2.getNickname());
                } else if (frontCompare < 0 && middleCompare < 0 && backCompare < 0) {
                    player1Score -= 6;
                    player2Score += 6;
                    log.info("玩家 {} 打枪成功！额外得6分，玩家 {} 额外扣6分", player2.getNickname(), player1.getNickname());
                }
                
                // 将本次比较的分数累加到房间的轮次得分中
                addScore(room, player1.getId(), player1Score);
                addScore(room, player2.getId(), player2Score);
                
                log.info("玩家 {} 与 玩家 {} 比较结果: {} vs {}", 
                    player1.getNickname(), player2.getNickname(), player1Score, player2Score);
            }
        }
        
        // 更新玩家总分
        room.getRoundScores().forEach((playerId, score) -> {
            Player player = findPlayer(room, playerId);
            player.setScore(player.getScore() + score);
            log.info("玩家 {} 本轮得分 {}，总分 {}", player.getNickname(), score, player.getScore());
        });
        
        log.info("房间 {} 本轮得分情况: {}", roomCode, room.getRoundScores());
        
        // 通知所有玩家状态更新，让前端显示结算结果
        log.info("=================== 发送结算结果通知 ===================");
        notifyRoomStatusChanged(room);
        log.info("=================== 结算结果通知已发送 ===================");
        
        // 保存当前得分记录的副本
        Map<Long, Integer> currentRoundScores = new HashMap<>(room.getRoundScores());
        
        // 记录每个玩家的得分情况，用于后续分析
        if (!currentRoundScores.isEmpty()) {
            log.info("房间 {} 第 {} 回合得分情况:", roomCode, room.getCurrentRound());
            currentRoundScores.forEach((playerId, score) -> {
                Player player = findPlayer(room, playerId);
                log.info("玩家 {} 得分: {}, 总分: {}", player.getNickname(), score, player.getScore());
            });
        }
        
        // 给前端留出时间显示结算结果，10秒后再重置玩家的准备状态
        new Thread(() -> {
            try {
                // 先等待3秒后再次发送结算通知，确保前端能够接收到
                Thread.sleep(3000);
                log.info("=================== 再次发送结算结果通知，确保前端显示 ===================");
                notifyRoomStatusChanged(room);
                log.info("=================== 结算结果再次通知已发送 ===================");
                
                // 再次尝试确保前端显示结算结果
                Thread.sleep(2000);
                log.info("=================== 第三次发送结算结果通知 ===================");
                notifyRoomStatusChanged(room);
                log.info("=================== 第三次结算结果通知已发送 ===================");
                
                // 然后等待5秒后重置玩家准备状态
                Thread.sleep(5000); // 总共等待10秒
                
                synchronized (room) {
                    // 重置本轮数据，但保留玩家总分
                    room.resetRound();
                    
                    // 检查游戏是否结束
                    if (room.getCurrentRound() >= room.getTotalRounds()) {
                        room.setStatus(RoomStatus.FINISHED);
                        log.info("房间 {} 游戏结束，当前回合 {}/{}", roomCode, room.getCurrentRound(), room.getTotalRounds());
                        
                        // 通知所有玩家游戏结束
                        notifyRoomStatusChanged(room);
                    } else {
                        // 修改：设置状态为等待中，重置所有玩家的准备状态，等待玩家重新准备
                        room.setCurrentRound(room.getCurrentRound() + 1);
                        log.info("房间 {} 进入准备阶段，等待玩家准备开始第 {} 回合", roomCode, room.getCurrentRound());
                        
                        // 重置所有玩家的准备状态
                        room.getPlayers().forEach(player -> {
                            player.setReady(false);
                            log.info("玩家 {} 的准备状态已重置", player.getNickname());
                        });
                        
                        // 设置房间状态为等待中
                        room.setStatus(RoomStatus.WAITING);
                        
                        // 结算已完成，不再清空得分记录
                        // room.getRoundScores().clear();
                        
                        // 通知所有玩家状态更新，显示需要重新准备
                        log.info("=================== 发送玩家重新准备通知 ===================");
                        notifyRoomStatusChanged(room);
                        log.info("=================== 玩家重新准备通知已发送 ===================");
                    }
                }
            } catch (InterruptedException e) {
                log.error("延迟重置玩家准备状态失败", e);
                Thread.currentThread().interrupt();
            }
        }).start();
    }
    
    @Override
    public int compareHands(List<Card> hand1, List<Card> hand2) {
        HandType type1 = getHandType(hand1);
        HandType type2 = getHandType(hand2);
        
        // 先比较牌型大小
        if (type1.ordinal() != type2.ordinal()) {
            return Integer.compare(type1.ordinal(), type2.ordinal());
        }
        
        // 牌型相同，比较分数
        int score1 = evaluateHand(hand1);
        int score2 = evaluateHand(hand2);
        return Integer.compare(score1, score2);
    }
    
    private void addScore(Room room, Long playerId, int score) {
        room.getRoundScores().merge(playerId, score, Integer::sum);
    }
    
    // 验证牌型是否合法
    private boolean validateHands(List<Card> frontHand, List<Card> middleHand, List<Card> backHand) {
        // 检查牌数是否正确
        if (frontHand.size() != 3 || middleHand.size() != 5 || backHand.size() != 5) {
            log.warn("牌型验证失败：牌数不正确，前墩={}, 中墩={}, 后墩={}", frontHand.size(), middleHand.size(), backHand.size());
            return false;
        }
        
        // 检查是否有重复的牌
        Set<String> cardSet = new java.util.HashSet<>();
        Stream.of(frontHand, middleHand, backHand)
            .flatMap(List::stream)
            .map(card -> card.getSuit().name() + card.getRank().name())
            .forEach(cardSet::add);
        if (cardSet.size() != 13) {
            log.warn("牌型验证失败：存在重复的牌，实际牌数={}", cardSet.size());
            return false;
        }
        
        // 获取每个墩位的牌型
        HandType backType = getHandType(backHand);
        HandType middleType = getHandType(middleHand);
        HandType frontType = getHandType(frontHand);
        
        log.info("牌型验证：后墩={}, 中墩={}, 前墩={}", backType, middleType, frontType);
        
        // 如果牌型相同，比较分数
        if (backType == middleType) {
            int backScore = evaluateHand(backHand);
            int middleScore = evaluateHand(middleHand);
            if (backScore <= middleScore) {
                log.warn("牌型验证失败：后墩分数 {} 不大于中墩分数 {}", backScore, middleScore);
                return false;
            }
        } else if (backType.ordinal() < middleType.ordinal()) { // 如果牌型不同，直接比较牌型大小
            log.warn("牌型验证失败：后墩牌型 {} 小于中墩牌型 {}", backType, middleType);
            return false;
        }
        
        if (middleType == frontType) {
            int middleScore = evaluateHand(middleHand);
            int frontScore = evaluateHand(frontHand);
            if (middleScore <= frontScore) {
                log.warn("牌型验证失败：中墩分数 {} 不大于前墩分数 {}", middleScore, frontScore);
                return false;
            }
        } else if (middleType.ordinal() < frontType.ordinal()) {
            log.warn("牌型验证失败：中墩牌型 {} 小于前墩牌型 {}", middleType, frontType);
            return false;
        }
        
        log.info("牌型验证通过");
        return true;
    }
    
    // 获取牌型
    private HandType getHandType(List<Card> cards) {
        Map<Card.Rank, Integer> rankCount = new HashMap<>();
        Map<Card.Suit, Integer> suitCount = new HashMap<>();
        
        // 统计每个点数和花色的数量
        for (Card card : cards) {
            rankCount.merge(card.getRank(), 1, Integer::sum);
            suitCount.merge(card.getSuit(), 1, Integer::sum);
        }
        
        // 检查是否同花
        boolean isFlush = suitCount.values().stream().anyMatch(count -> count == cards.size());
        
        // 检查是否顺子
        boolean isStraight = false;
        if (cards.size() == 5) {
            List<Integer> straightCheckValues = cards.stream()
                .map(card -> card.getRank().getValue())
                .sorted()
                .collect(Collectors.toList());
            
            // 检查普通顺子
            if (straightCheckValues.get(4) - straightCheckValues.get(0) == 4 && 
                straightCheckValues.stream().distinct().count() == 5) {
                isStraight = true;
            } 
            // 处理A2345的特殊情况
            else if (straightCheckValues.contains(14)) { // 如果有A
                // 检查是否为A2345
                if (straightCheckValues.contains(2) && 
                    straightCheckValues.contains(3) && 
                    straightCheckValues.contains(4) && 
                    straightCheckValues.contains(5) && 
                    straightCheckValues.contains(14)) {
                    isStraight = true;
                }
            }
        }
        
        // 判断牌型
        if (isFlush && isStraight) {
            // 检查是否皇家同花顺 (10-J-Q-K-A)
            List<Integer> royalCheckValues = cards.stream()
                .map(card -> card.getRank().getValue())
                .collect(Collectors.toList());
                
            if (royalCheckValues.contains(10) && 
                royalCheckValues.contains(11) && 
                royalCheckValues.contains(12) && 
                royalCheckValues.contains(13) && 
                royalCheckValues.contains(14)) { // 使用14代表A
                return HandType.ROYAL_FLUSH;
            }
            return HandType.STRAIGHT_FLUSH;
        }
        
        // 检查四条
        if (rankCount.values().stream().anyMatch(count -> count == 4)) {
            return HandType.FOUR_OF_A_KIND;
        }
        
        // 检查葫芦
        if (rankCount.values().stream().anyMatch(count -> count == 3) &&
            rankCount.values().stream().anyMatch(count -> count == 2)) {
            return HandType.FULL_HOUSE;
        }
        
        if (isFlush) {
            return HandType.FLUSH;
        }
        
        if (isStraight) {
            return HandType.STRAIGHT;
        }
        
        // 检查三条
        if (rankCount.values().stream().anyMatch(count -> count == 3)) {
            return HandType.THREE_OF_A_KIND;
        }
        
        // 检查两对
        long pairCount = rankCount.values().stream().filter(count -> count == 2).count();
        if (pairCount == 2) {
            return HandType.TWO_PAIR;
        }
        
        // 检查一对
        if (pairCount == 1) {
            return HandType.PAIR;
        }
        
        return HandType.HIGH_CARD;
    }
    
    // 评估牌型分数
    private int evaluateHand(List<Card> cards) {
        int score = 0;
        Map<Card.Rank, Integer> rankCount = new HashMap<>();
        
        // 统计每个点数的数量
        for (Card card : cards) {
            rankCount.merge(card.getRank(), 1, Integer::sum);
        }
        
        // 根据不同牌型计算分数
        HandType handType = getHandType(cards);
        switch (handType) {
            case ROYAL_FLUSH:
                return 1000000; // 最高分
                
            case STRAIGHT_FLUSH:
                score = 900000;
                // 对于A2345的同花顺特殊处理
                List<Integer> sfValues = cards.stream()
                    .map(card -> card.getRank().getValue())
                    .sorted()
                    .collect(Collectors.toList());
                
                if (sfValues.contains(14) && sfValues.contains(2) && !sfValues.contains(13)) { // A2345的情况
                    score += 5; // A2345作为最小的顺子，得分为5
                } else {
                    score += getHighestRank(cards);
                }
                break;
                
            case FOUR_OF_A_KIND:
                score = 800000;
                // 找出四条的点数，按点数大小排序
                List<Card.Rank> sortedRanks = rankCount.entrySet().stream()
                    .sorted((e1, e2) -> {
                        if (e1.getValue() != e2.getValue()) {
                            return Integer.compare(e2.getValue(), e1.getValue()); // 先按数量降序
                        }
                        return Integer.compare(e2.getKey().getValue(), e1.getKey().getValue()); // 再按点数降序
                    })
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
                
                // 四条的牌点数 * 100 + 单张的牌点数
                score += sortedRanks.get(0).getValue() * 100;
                if (sortedRanks.size() > 1) {
                    score += sortedRanks.get(1).getValue();
                }
                break;
                
            case FULL_HOUSE:
                score = 700000;
                // 找出三条和对子的点数
                for (Map.Entry<Card.Rank, Integer> entry : rankCount.entrySet()) {
                    if (entry.getValue() == 3) {
                        score += entry.getKey().getValue() * 100;
                    } else if (entry.getValue() == 2) {
                        score += entry.getKey().getValue();
                    }
                }
                break;
                
            case FLUSH:
                score = 600000;
                score += getHighestRank(cards);
                break;
                
            case STRAIGHT:
                score = 500000;
                // 对于A2345的顺子特殊处理
                List<Integer> stValues = cards.stream()
                    .map(card -> card.getRank().getValue())
                    .sorted()
                    .collect(Collectors.toList());
                
                if (stValues.contains(14) && stValues.contains(2) && !stValues.contains(13)) { // A2345的情况
                    score += 5; // A2345作为最小的顺子，得分为5
                } else {
                    score += getHighestRank(cards);
                }
                break;
                
            case THREE_OF_A_KIND:
                score = 400000;
                // 找出三条的点数
                for (Map.Entry<Card.Rank, Integer> entry : rankCount.entrySet()) {
                    if (entry.getValue() == 3) {
                        score += entry.getKey().getValue() * 100;
                    } else {
                        score += entry.getKey().getValue();
                    }
                }
                break;
                
            case TWO_PAIR:
                score = 300000;
                int pairCount = 0;
                for (Map.Entry<Card.Rank, Integer> entry : rankCount.entrySet()) {
                    if (entry.getValue() == 2) {
                        score += entry.getKey().getValue() * Math.pow(100, 2 - pairCount);
                        pairCount++;
                    } else {
                        score += entry.getKey().getValue();
                    }
                }
                break;
                
            case PAIR:
                score = 200000;
                // 找出对子的点数
                for (Map.Entry<Card.Rank, Integer> entry : rankCount.entrySet()) {
                    if (entry.getValue() == 2) {
                        score += entry.getKey().getValue() * 100;
                    } else {
                        score += entry.getKey().getValue();
                    }
                }
                break;
                
            case HIGH_CARD:
                score = 100000;
                score += getHighestRank(cards);
                break;
        }
        
        return score;
    }
    
    private int getHighestRank(List<Card> cards) {
        return cards.stream()
            .mapToInt(card -> card.getRank().getValue())
            .max()
            .orElse(0);
    }
    
    private void startGame(Room room) {
        log.info("开始游戏，房间: {}, 当前回合: {}, 房间状态: {}", 
                room.getRoomCode(), room.getCurrentRound(), room.getStatus());
        
        // 重置游戏状态
        room.setStatus(RoomStatus.PLAYING);
        if (room.getCurrentRound() == 0) {
            room.setCurrentRound(1);
            room.setTotalRounds(13); // 默认13轮
        }
        
        log.info("游戏状态已更新为PLAYING，当前回合: {}", room.getCurrentRound());
        
        // 重置所有玩家的手牌
        List<Card> deck = generateDeck();
        Collections.shuffle(deck);
        
        // 确保每个玩家精确获得13张牌
        int playerCount = room.getPlayers().size();
        log.info("房间 {} 开始发牌，玩家数: {}", room.getRoomCode(), playerCount);
        
        // 为每个玩家分配13张牌
        for (int i = 0; i < playerCount; i++) {
            Player player = room.getPlayers().get(i);
            List<Card> playerCards = new ArrayList<>();
            
            // 取13张牌给当前玩家
            for (int j = 0; j < 13; j++) {
                int cardIndex = i * 13 + j;
                // 确保不越界
                if (cardIndex < deck.size()) {
                    playerCards.add(deck.get(cardIndex));
                }
            }
            
            player.setCards(playerCards);
            player.setReady(false); // 确保开始新回合时所有玩家的准备状态为未准备，这样就可以在提交牌型时标记为已准备
            log.info("玩家 {} 获得 {} 张牌，准备状态已重置", player.getNickname(), playerCards.size());
        }
        
        // 清空提交的牌型
        room.getSubmittedHands().clear();
        
        // 清空上一轮的得分记录
        room.getRoundScores().clear();
        
        // 设置当前玩家为第一个玩家
        room.setCurrentPlayerId(room.getPlayers().get(0).getId());
        
        log.info("房间 {} 游戏开始，当前回合 {}/{}, 房间状态: {}", 
                room.getRoomCode(), room.getCurrentRound(), room.getTotalRounds(), room.getStatus());
    }
    
    private void finishRound(Room room, Player winner) {
        // 更新分数
        winner.setScore(winner.getScore() + 1);
        
        // 检查是否达到总回合数
        if (room.getCurrentRound() >= room.getTotalRounds()) {
            room.setStatus(RoomStatus.FINISHED);
        } else {
            // 开始新回合
            room.setCurrentRound(room.getCurrentRound() + 1);
            startGame(room);
        }
    }
    
    private void nextPlayer(Room room) {
        List<Player> players = room.getPlayers();
        int currentIndex = -1;
        
        // 找到当前玩家的索引
        for (int i = 0; i < players.size(); i++) {
            if (players.get(i).getId().equals(room.getCurrentPlayerId())) {
                currentIndex = i;
                break;
            }
        }
        
        // 设置下一个玩家
        int nextIndex = (currentIndex + 1) % players.size();
        room.setCurrentPlayerId(players.get(nextIndex).getId());
    }
    
    @Override
    public Room getRoom(String roomCode) {
        return rooms.get(roomCode);
    }
    
    private Room getModelRoom(String roomCode) {
        Room room = rooms.get(roomCode);
        if (room == null) {
            throw new BusinessException("房间不存在");
        }
        return room;
    }
    
    private Player findPlayer(Room room, Long userId) {
        return room.getPlayers().stream()
                .filter(p -> p.getId().equals(userId))
                .findFirst()
                .orElseThrow(() -> new BusinessException("玩家不在房间中"));
    }
    
    private Player createPlayer(User user) {
        Player player = new Player();  // 使用无参构造函数
        player.setId(user.getId());
        player.setNickname(user.getNickname());
        player.setReady(false);
        player.setScore(0);
        player.setCards(new ArrayList<>());
        return player;
    }
    
    private RoomVO convertToRoomVO(Room room) {
        RoomVO vo = new RoomVO();
        vo.setRoomCode(room.getRoomCode());
        vo.setStatus(room.getStatus());
        vo.setPlayerCount(room.getPlayers().size());
        vo.setCreateTime(new java.sql.Date(room.getCreateTime().getTime()));
        return vo;
    }
    
    private List<String> initializeDeck() {
        List<String> deck = new ArrayList<>();
        String[] suits = {"♠", "♥", "♣", "♦"};
        String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
        
        for (String suit : suits) {
            for (String rank : ranks) {
                deck.add(suit + rank);
            }
        }
        return deck;
    }
    
    private String generateRoomCode() {
        return UUID.randomUUID().toString().substring(0, 6).toUpperCase();
    }
    
    // 添加WebSocket通知方法
    private void notifyRoomStatusChanged(Room room) {
        try {
            log.info("开始向玩家发送房间状态通知，房间: {}, 玩家数: {}", room.getRoomCode(), room.getPlayers().size());
            
            // 先验证每个玩家的牌数是否为13张
            if (room.getStatus() == RoomStatus.PLAYING) {
                room.getPlayers().forEach(player -> {
                    int cardCount = player.getCards().size();
                    log.info("玩家 {} 当前持有 {} 张牌", player.getNickname(), cardCount);
                    if (cardCount != 13 && !room.getSubmittedHands().containsKey(player.getId())) {
                        log.warn("警告: 玩家 {} 的牌数不是13张，而是 {} 张", player.getNickname(), cardCount);
                    }
                });
            }
            
            room.getPlayers().forEach(player -> {
                RoomStatusVO status = getRoomStatus(room.getRoomCode(), player.getId());
                log.info("向玩家 {} 发送WebSocket消息，状态: {}, 轮次: {}, 已准备玩家数: {}, 回合得分: {}", 
                         player.getNickname(), status.getStatus(), status.getCurrentRound(), 
                         status.getReadyPlayersCount(), status.getRoundScores());
                
                // 检查结算数据
                if (status.getRoundScores() != null && !status.getRoundScores().isEmpty()) {
                    log.info("结算数据将发送给玩家 {}: {}", player.getNickname(), status.getRoundScores());
                }
                
                messagingTemplate.convertAndSendToUser(
                    player.getId().toString(),
                    "/queue/room-status",
                    status
                );
                
                log.info("WebSocket消息已发送给玩家: {}", player.getNickname());
            });
        } catch (Exception e) {
            log.error("发送WebSocket通知失败", e);
        }
    }
    
    // 将字符串转换为Card对象
    private Card stringToCard(String cardStr) {
        // 解析花色和点数
        String suitChar = cardStr.substring(0, 1);
        String rankStr = cardStr.substring(1);
        
        // 映射花色符号到枚举
        Card.Suit suit;
        switch (suitChar) {
            case "♠":
                suit = Card.Suit.SPADES;
                break;
            case "♥":
                suit = Card.Suit.HEARTS;
                break;
            case "♦":
                suit = Card.Suit.DIAMONDS;
                break;
            case "♣":
                suit = Card.Suit.CLUBS;
                break;
            default:
                throw new IllegalArgumentException("Unknown card suit: " + suitChar);
        }
        
        // 映射点数到枚举
        Card.Rank rank;
        switch (rankStr) {
            case "A":
                rank = Card.Rank.ACE;
                break;
            case "2":
                rank = Card.Rank.TWO;
                break;
            case "3":
                rank = Card.Rank.THREE;
                break;
            case "4":
                rank = Card.Rank.FOUR;
                break;
            case "5":
                rank = Card.Rank.FIVE;
                break;
            case "6":
                rank = Card.Rank.SIX;
                break;
            case "7":
                rank = Card.Rank.SEVEN;
                break;
            case "8":
                rank = Card.Rank.EIGHT;
                break;
            case "9":
                rank = Card.Rank.NINE;
                break;
            case "10":
                rank = Card.Rank.TEN;
                break;
            case "J":
                rank = Card.Rank.JACK;
                break;
            case "Q":
                rank = Card.Rank.QUEEN;
                break;
            case "K":
                rank = Card.Rank.KING;
                break;
            default:
                throw new IllegalArgumentException("Unknown card rank: " + rankStr);
        }
        
        return new Card(suit, rank);
    }
    
    // 生成一副牌
    private List<Card> generateDeck() {
        List<Card> deck = new ArrayList<>();
        for (Card.Suit suit : Card.Suit.values()) {
            for (Card.Rank rank : Card.Rank.values()) {
                deck.add(new Card(suit, rank));
            }
        }
        return deck;
    }
}